package com.redmoon.oa.pvg;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Iterator;

import cn.js.fan.base.ObjectBlockIterator;
import cn.js.fan.base.ObjectDb;
import cn.js.fan.db.Conn;
import cn.js.fan.db.PrimaryKey;
import cn.js.fan.db.SQLFilter;
import cn.js.fan.util.DateUtil;
import cn.js.fan.util.StrUtil;

import com.cloudweb.oa.utils.ConstUtil;
import com.cloudwebsoft.framework.util.LogUtil;
import com.redmoon.oa.Config;
import com.redmoon.oa.person.UserDb;
import org.apache.poi.ss.formula.functions.T;

/**
 *
 * <p>Title: 在线用户详细信息管理</p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>Company: </p>
 *
 * @author not attributable
 * @version 1.0
 */
public class OnlineUserDb extends ObjectDb {
    public static final String ALLCOUNTSQL = "select count(*) from oa_online";

    private String sessionId;
    
    private String client;
    
    public OnlineUserDb() {
    }

    public OnlineUserDb(String name) {
        this.name = name;
        init();
        load();
    }

    public OnlineUserDb getOnlineUserDb(String name) {
        return (OnlineUserDb)getObjectDb(name);
    }

    public ObjectBlockIterator getOnlineUsers(String query, int startIndex, int endIndex) {
        // if (!SecurityUtil.isValidSql(query))
        //     return null;
        //可能取得的infoBlock中的元素的顺序号小于endIndex
        Object[] docBlock = getObjectBlock(query, startIndex);
        return new ObjectBlockIterator(this, docBlock, query, startIndex, endIndex);
    }

    public void refreshOnlineUser() {
        // 删除超时在位用户,超时时间为20分钟
        Config cfg = new Config();
        int expire = cfg.getInt("refreshOnlineExpire");

        long expiremilli = expire * 1000;
        long expiretime = System.currentTimeMillis() - expiremilli;
        Date d = new Date(expiretime);
        String sql = "select name from oa_online where (stay_time is not null and stay_time<" + SQLFilter.getDateStr(DateUtil.format(d, "yyyy-MM-dd"), "yyyy-MM-dd") + ") or (stay_time_mobile is not null and stay_time_mobile<" + SQLFilter.getDateStr(DateUtil.format(d, "yyyy-MM-dd"), "yyyy-MM-dd") + ")";
        for (Object o : list(sql)) {
            OnlineUserDb olu = (OnlineUserDb) o;
            olu.setOnline(false);
            olu.save();
        }
        OnlineUserCache uc = new OnlineUserCache(this);
        uc.refreshCreate();
    }

    @Override
    public boolean create() {
        boolean isvalid;
        String sql = "insert into oa_online (name,ip,covered,login_time,stay_time,session_id,client,login_time_mobile,stay_time_mobile,client_mobile,ip_mobile,is_online) values (?,?,?,?,?,?,?,?,?,?,?,1)";
        Conn conn = new Conn(connname);
        try {
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setString(1, name);
            ps.setString(2, ip);
            ps.setInt(3, covered?1:0);
            if (loginTime != null) {
                ps.setTimestamp(4, new Timestamp(loginTime.getTime()));
            } else {
                ps.setTimestamp(4, null);
            }
            ps.setTimestamp(5, new Timestamp(new Date().getTime()));
            ps.setString(6, sessionId);
            ps.setString(7, client);
            if (loginTimeMobile != null) {
                ps.setTimestamp(8, new Timestamp(loginTimeMobile.getTime()));
            } else {
                ps.setTimestamp(8, null);
            }
            if (stayTimeMobile != null) {
                ps.setTimestamp(9, new Timestamp(stayTimeMobile.getTime()));
            } else {
                ps.setTimestamp(9, null);
            }
            ps.setString(10, clientMobile);
            ps.setString(11, ipMobile);
            isvalid = conn.executePreUpdate() == 1;
        } catch (SQLException e) {
            com.cloudwebsoft.framework.util.LogUtil.getLog(getClass()).error("create:" + e.getMessage());
            isvalid = false;
        } finally {
            conn.close();
        }
        if (isvalid) {
            OnlineUserCache uc = new OnlineUserCache(this);
            uc.refreshCreate();
        }
        // 刷新在线缓存
        OnlineUserCache oc = new OnlineUserCache(this);
        oc.refreshCreate();

        // 刷新超时在线用户人数，改为在调度中刷新
        // refreshOnlineUser();

        return isvalid;
    }

    @Override
    public ObjectDb getObjectDb(Object primaryKeyValue) {
        OnlineUserCache uc = new OnlineUserCache(this);
        primaryKey.setValue(primaryKeyValue);
        return uc.getObjectDb(primaryKey);
    }

    @Override
    public synchronized boolean del() {
        // 记录在线时长
        if (loginTime != null) {
            UserDb ud = new UserDb();
            long millis = System.currentTimeMillis() - loginTime.getTime();
            float hour = (float) millis / 3600000;
            ud = ud.getUserDb(name);
            ud.setOnlineTime(ud.getOnlineTime() + hour);
            ud.save();
        }

        boolean re = false;
        String sql = "delete from oa_online where name=?";
        Conn conn = new Conn(connname);
        try {
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setString(1, name);
            re = conn.executePreUpdate() == 1;
        } catch (SQLException e) {
            LogUtil.getLog(getClass()).error(e);
        } finally {
            conn.close();
        }
        if (re) {
            OnlineUserCache uc = new OnlineUserCache(this);
            primaryKey.setValue(name);
            uc.refreshDel(primaryKey);
            uc.refreshCreate();
        }
        return re;
    }

    @Override
    public int getObjectCount(String sql) {
        OnlineUserCache uc = new OnlineUserCache(this);
        return uc.getObjectCount(sql);
    }

    @Override
    public Object[] getObjectBlock(String query, int startIndex) {
        OnlineUserCache dcm = new OnlineUserCache(this);
        return dcm.getObjectBlock(query, startIndex);
    }

    @Override
    public ObjectDb getObjectRaw(PrimaryKey pk) {
        return new OnlineUserDb(pk.getStrValue());
    }

    @Override
    public void setQueryCreate() {
    }

    @Override
    public void setQueryDel() {

    }

    @Override
    public void setQueryList() {
        // 下句会导致并发效率问题，当人数达到70人左右时
        // QUERY_LIST = "select o.name,d.dept_code from oa_online o, dept_user d where o.name=d.user_name order by d.dept_code asc, o.login_time asc";
        QUERY_LIST = "select name from oa_online where name<>'system' order by login_time asc";
    }

    @Override
    public void setQuerySave() {
        this.QUERY_SAVE =
            "update oa_online set ip=?,doing=?,login_time=?,stay_time=?,covered=?,session_id=?,client=?,login_time_mobile=?,stay_time_mobile=?,client_mobile=?,ip_mobile=?,is_online=? where name=?";
    }

    @Override
    public synchronized boolean save() {
        boolean re = false;
        Conn conn = new Conn(connname);
        try {
            PreparedStatement ps = conn.prepareStatement(QUERY_SAVE);
            ps.setString(1, ip);
            ps.setString(2, doing);
            if (loginTime != null) {
                ps.setTimestamp(3, new Timestamp(loginTime.getTime()));
            } else {
                ps.setTimestamp(3, null);
            }
            if (stayTimeMobile != null) {
                ps.setTimestamp(4, new Timestamp(stayTime.getTime()));
            } else {
                ps.setTimestamp(4, null);
            }
            ps.setInt(5, covered?1:0);
            ps.setString(6, sessionId);
            ps.setString(7, client);
            if (loginTimeMobile != null) {
                ps.setTimestamp(8, new Timestamp(loginTimeMobile.getTime()));
            } else {
                ps.setTimestamp(8, null);
            }
            if (stayTimeMobile != null) {
                ps.setTimestamp(9, new Timestamp(stayTimeMobile.getTime()));
            } else {
                ps.setTimestamp(9, null);
            }
            ps.setString(10, clientMobile);
            ps.setString(11, ipMobile);
            ps.setInt(12, online?1:0);
            ps.setString(13, name);
            re = conn.executePreUpdate() == 1;
        } catch (Exception e) {
            LogUtil.getLog(getClass()).error("save:" + e.getMessage());
        } finally {
            conn.close();
        }
        if (re) {
            OnlineUserCache uc = new OnlineUserCache(this);
            primaryKey.setValue(name);
            uc.refreshSave(primaryKey);
        }
        return re;
    }

    @Override
    public void setPrimaryKey() {
        primaryKey = new PrimaryKey("name", PrimaryKey.TYPE_STRING);
    }

    @Override
    public void setQueryLoad() {
        QUERY_LOAD = "select ip,doing,login_time,stay_time,covered,session_id,client,login_time_mobile,stay_time_mobile,client_mobile,ip_mobile,is_online from oa_online where name=?";
    }

    @Override
    public synchronized void load() {
        Conn conn = new Conn(connname);
        ResultSet rs;
        try {
            PreparedStatement pstmt = conn.prepareStatement(QUERY_LOAD);
            pstmt.setString(1, name);
            rs = conn.executePreQuery();
            if (rs != null && rs.next()) {
                ip = StrUtil.getNullString(rs.getString(1));
                doing = rs.getString(2);
                loginTime = rs.getTimestamp(3);
                stayTime = rs.getTimestamp(4);
                covered = rs.getInt(5) == 1;
                sessionId = StrUtil.getNullStr(rs.getString(6));
                client = StrUtil.getNullStr(rs.getString(7));
                loginTimeMobile = rs.getTimestamp(8);
                stayTimeMobile = rs.getTimestamp(9);
                clientMobile = rs.getString(10);
                ipMobile = StrUtil.emptyTo(rs.getString(11), "");
                online = rs.getInt(12) == 1;
                loaded = true;
            }
        } catch (SQLException e) {
            com.cloudwebsoft.framework.util.LogUtil.getLog(getClass()).error(e);
        } finally {
            conn.close();
        }
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public void setDoing(String action) {
        this.doing = action;
    }

    public void setLoginTime(java.util.Date loginTime) {
        this.loginTime = loginTime;
    }

    public void setStayTime(java.util.Date stayTime) {
        this.stayTime = stayTime;
    }

    public void setGuest(boolean guest) {
        this.guest = guest;
    }

    public void setCovered(boolean covered) {
        this.covered = covered;
    }

    public void setSessionId(String sessionId) {
        this.sessionId = sessionId;
    }

    public String getName() {
        return name;
    }

    public String getIp() {
        return ip;
    }

    public String getDoing() {
        return doing;
    }

    public java.util.Date getLoginTime() {
        return loginTime;
    }

    public java.util.Date getStayTime() {
        return stayTime;
    }

    public boolean isGuest() {
        return guest;
    }

    public boolean isCovered() {
        return covered;
    }

    public String getSessionId() {
        return sessionId;
    }

    public int getAllCount() {
        OnlineUserCache ou = new OnlineUserCache(this);
        return ou.getAllCount();
    }

    public void setClient(String client) {
		this.client = client;
	}

	public String getClient() {
		return client;
	}

	private String name;
    private String ip;
    private String doing;
    private java.util.Date loginTime;
    private java.util.Date stayTime;
    private boolean guest = false;
    private boolean covered = false;

    public Date getLoginTimeMobile() {
        return loginTimeMobile;
    }

    public void setLoginTimeMobile(Date loginTimeMobile) {
        this.loginTimeMobile = loginTimeMobile;
    }

    public Date getStayTimeMobile() {
        return stayTimeMobile;
    }

    public void setStayTimeMobile(Date stayTimeMobile) {
        this.stayTimeMobile = stayTimeMobile;
    }

    public String getClientMobile() {
        return clientMobile;
    }

    public void setClientMobile(String clientMobile) {
        this.clientMobile = clientMobile;
    }

    private Date loginTimeMobile;
    private Date stayTimeMobile;
    private String clientMobile;

    public String getIpMobile() {
        return ipMobile;
    }

    public void setIpMobile(String ipMobile) {
        this.ipMobile = ipMobile;
    }

    private String ipMobile;

    public boolean isOnline() {
        return online;
    }

    public void setOnline(boolean online) {
        this.online = online;
    }

    private boolean online;
}
